#include <iostream>
#include <utility>  // for std::swap

using namespace std;


namespace test3 {
    class Intvec
    {
    public:
        explicit Intvec(size_t num = 0)
            : m_size(num), m_data(new int[m_size])
        {
            log("constructor");
        }

        ~Intvec()
        {
            log("destructor");
            delete[] m_data;
        }

        Intvec(const Intvec& other)
            : m_size(other.m_size), m_data(new int[m_size])
        {
            log("copy constructor");
            for (size_t i = 0; i < m_size; ++i)
                m_data[i] = other.m_data[i];
        }

        Intvec(Intvec&& other)
            : m_size(0), m_data(nullptr)
        {
            log("move constructor");
            // swap the members of this class with the members of other
            std::swap(m_size, other.m_size);
            std::swap(m_data, other.m_data);
        }

        Intvec& operator=(const Intvec& other)
        {
            log("copy assignment operator");
            Intvec tmp(other);
            std::swap(m_size, tmp.m_size);
            std::swap(m_data, tmp.m_data);
            return *this;
        }

        Intvec& operator=(Intvec&& other)
        {
            log("move assignment operator");
            std::swap(m_size, other.m_size);
            std::swap(m_data, other.m_data);
            return *this;
        }

    private:
        void log(const char* msg)
        {
            cout << "[" << this << "] " << msg << "\n";
        }

        size_t m_size;
        int* m_data;
    };

    int main4() {
        Intvec v1(20);
        Intvec v2;

        cout << "assigning lvalue..." << endl;
        v2 = v1;
        cout << "end assigning lvalue..." << endl;

        cout << "assigning rvalue..." << endl;
        v2 = Intvec(33);
        cout << "end assigning rvalue..." << endl;

        return 0;
    }
}